package arg

import (
	"db2s/global"
	"db2s/outPut"
	"fmt"
	"github.com/gurkankaymak/hocon"
	"reflect"
	"strings"
)

/*
		resultOut {
			method = xls
			generalResult = true
			tty = bar
			xls {
					ResultSheetName  = "aaa"
					TerminalSheetName = "bbb"
					XlsFileName      = "ccc"
					XlsSafetySwitch   = true
					XlsResultTail    = ""
			}
	}
*/

func (rc *ConfigParameter) structXlsDefinitionFunc() (map[string]any, map[string]string, map[string]reflect.Type) {
	var (
		sheetName      map[string]any
		sheetTail      map[string]string
		sheetStructMap map[string]reflect.Type
	)
	sheetName = map[string]any{"terminal": "db2s_terminal",
		"sheetName": global.AnySliceToStringSlice(global.StructNameJsonToSlice(global.MetaTitleSheetName{})),
		"fileName":  "db2s_struct_Result"}
	sheetTail = map[string]string{
		"terminal":      global.AnySliceToString(global.StructNameJsonToSlice(global.TStruct{})),
		"convertRecord": global.AnySliceToString(global.StructNameJsonToSlice(global.MetaConvertTitle{})),
		"execRecord":    global.AnySliceToString(global.StructNameJsonToSlice(global.MetaExecTitle{})),
		"missTable":     global.AnySliceToString(global.StructNameJsonToSlice(global.XStructMissTable{}))}
	sheetStructMap = map[string]reflect.Type{
		"terminal":      reflect.TypeOf(global.TStruct{}),
		"convertRecord": reflect.TypeOf(global.MetaConvertTitle{}),
		"execRecord":    reflect.TypeOf(global.MetaExecTitle{}),
		"missTable":     reflect.TypeOf(global.XStructMissTable{}),
	}
	return sheetName, sheetTail, sheetStructMap
}

func (rc *ConfigParameter) syncXlsDefinitionFunc() (map[string]any, map[string]string, map[string]reflect.Type) {
	var (
		sheetName      map[string]any
		sheetTail      map[string]string
		sheetStructMap map[string]reflect.Type
	)
	sheetName = map[string]any{"terminal": "terminal",
		"sheetName": global.AnySliceToStringSlice(global.StructNameJsonToSlice(global.XSyncSheetName{})),
		"fileName":  "db2s_sync_Result"}
	sheetTail = map[string]string{
		"terminal":    global.AnySliceToString(global.StructNameJsonToSlice(global.TSync{})),
		"sync_result": global.AnySliceToString(global.StructNameJsonToSlice(global.XSyncSheetTail{})),
		"missTable":   global.AnySliceToString(global.StructNameJsonToSlice(global.XStructMissTable{}))}
	sheetStructMap = map[string]reflect.Type{
		"terminal":    reflect.TypeOf(global.TSync{}),
		"sync_result": reflect.TypeOf(global.XSyncSheetTail{}),
		"missTable":   reflect.TypeOf(global.XStructMissTable{})}

	return sheetName, sheetTail, sheetStructMap
}
func (rc *ConfigParameter) taskXlsDefinitionFunc() (map[string]any, map[string]string, map[string]reflect.Type) {
	var (
		sheetName      map[string]any
		sheetTail      map[string]string
		sheetStructMap map[string]reflect.Type
	)
	sheetName = map[string]any{"terminal": "terminal",
		"sheetName": global.AnySliceToStringSlice(global.StructNameJsonToSlice(global.XTaskSheetName{})),
		"fileName":  "db2s_task_Result"}
	sheetTail = map[string]string{
		"terminal":    global.AnySliceToString(global.StructNameJsonToSlice(outPut.Task{})),
		"task_result": global.AnySliceToString(global.StructNameJsonToSlice(global.XTaskSheetTail{})),
		"missTable":   global.AnySliceToString(global.StructNameJsonToSlice(global.XStructMissTable{}))}
	sheetStructMap = map[string]reflect.Type{
		"terminal":    reflect.TypeOf(outPut.Task{}),
		"task_result": reflect.TypeOf(global.XTaskSheetTail{}),
		"missTable":   reflect.TypeOf(global.XStructMissTable{})}

	return sheetName, sheetTail, sheetStructMap
}
func (rc *ConfigParameter) hotSqlXlsDefinitionFunc() (map[string]any, map[string]string, map[string]reflect.Type) {
	var (
		sheetName map[string]any
		sheetTail map[string]string
	)
	sheetName = map[string]any{
		"terminal":  "db2s_terminal",
		"sheetName": global.AnySliceToStringSlice(global.StructNameJsonToSlice(global.XHotSqlSheetName{})),
		"fileName":  "db2s_hotSql_Result"}
	sheetTail = map[string]string{
		"db2s_terminal": global.AnySliceToString(global.StructNameJsonToSlice(global.Thotsql{})),
		"sync_result":          global.AnySliceToString(global.StructNameJsonToSlice(global.XHotSqlSheetHead{})),
		"missTable":            global.AnySliceToString(global.StructNameJsonToSlice(global.XStructMissTable{}))}
	return sheetName, sheetTail, nil
}
func (rc *ConfigParameter) loadXlsDefinitionFunc() (map[string]any, map[string]string, map[string]reflect.Type) {
	var (
		sheetName map[string]any
		sheetTail map[string]string
	)
	sheetName = map[string]any{"terminal": "db2s_terminal",
		"sheetName": global.AnySliceToStringSlice(global.StructNameJsonToSlice(global.XLoadSheetName{})),
		"fileName":  "db2s_load_Result"}
	sheetTail = map[string]string{
		"db2s_terminal": global.AnySliceToString(global.StructNameJsonToSlice(global.TLoad{})),
		"load_result":          global.AnySliceToString(global.StructNameJsonToSlice(global.XLoadSheetTail{})),
		"missTable":            global.AnySliceToString(global.StructNameJsonToSlice(global.XStructMissTable{})),
	}
	return sheetName, sheetTail, nil
}
func (rc *ConfigParameter) countXlsDefinitionFunc() (map[string]any, map[string]string, map[string]reflect.Type) {
	var (
		sheetName      map[string]any
		sheetTail      map[string]string
		sheetStructMap map[string]reflect.Type
	)
	sheetName = map[string]any{"terminal": "terminal",
		"sheetName": global.AnySliceToStringSlice(global.StructNameJsonToSlice(global.XCountSheetName{})),
		"fileName":  "db2s_count_Result"}
	sheetTail = map[string]string{
		"terminal":     global.AnySliceToString(global.StructNameJsonToSlice(global.TCount{})),
		"count_result": global.AnySliceToString(global.StructNameJsonToSlice(global.XCountSheetTail{})),
		"missTable":    global.AnySliceToString(global.StructNameJsonToSlice(global.XStructMissTable{})),
	}
	sheetStructMap = map[string]reflect.Type{
		"terminal":     reflect.TypeOf(global.TCount{}),
		"count_result": reflect.TypeOf(global.XCountSheetTail{}),
		"missTable":    reflect.TypeOf(global.XStructMissTable{}),
	}
	return sheetName, sheetTail, sheetStructMap
}
func (rc *ConfigParameter) rowsXlsDefinitionFunc() (map[string]any, map[string]string, map[string]reflect.Type) {
	var (
		sheetName      map[string]any
		sheetTail      map[string]string
		sheetStructMap map[string]reflect.Type
	)
	sheetName = map[string]any{"terminal": "terminal",
		"sheetName": global.AnySliceToStringSlice(global.StructNameJsonToSlice(global.XRowsSheetName{})),
		"fileName":  "db2s_rows_Result"}
	sheetTail = map[string]string{
		"terminal":    global.AnySliceToString(global.StructNameJsonToSlice(outPut.TPod{})),
		"rows_result": global.AnySliceToString(global.StructNameJsonToSlice(global.XRowsSheetTail{})),
		"missTable":   global.AnySliceToString(global.StructNameJsonToSlice(global.XStructMissTable{})),
	}
	sheetStructMap = map[string]reflect.Type{
		"terminal":    reflect.TypeOf(outPut.TPod{}),
		"rows_result": reflect.TypeOf(global.XRowsSheetTail{}),
		"missTable":   reflect.TypeOf(global.XStructMissTable{}),
	}
	return sheetName, sheetTail, sheetStructMap
}
func (rc *ConfigParameter) sampXlsDefinitionFunc() (map[string]any, map[string]string, map[string]reflect.Type) {
	var (
		sheetName      map[string]any
		sheetTail      map[string]string
		sheetStructMap map[string]reflect.Type
	)
	sheetName = map[string]any{"terminal": "terminal",
		"sheetName": global.AnySliceToStringSlice(global.StructNameJsonToSlice(global.XSampSheetName{})),
		"fileName":  "db2s_samp_Result"}
	sheetTail = map[string]string{
		"terminal":    global.AnySliceToString(global.StructNameJsonToSlice(global.Tsamp{})),
		"samp_result": global.AnySliceToString(global.StructNameJsonToSlice(global.XSampsheetTatil{})),
		"missTable":   global.AnySliceToString(global.StructNameJsonToSlice(global.XStructMissTable{})),
	}
	sheetStructMap = map[string]reflect.Type{
		"terminal":    reflect.TypeOf(global.Tsamp{}),
		"rows_result": reflect.TypeOf(global.XSampsheetTatil{}),
		"missTable":   reflect.TypeOf(global.XStructMissTable{}),
	}
	return sheetName, sheetTail, sheetStructMap
}
func modeFuncMap() map[string]reflect.Value {
	return map[string]reflect.Value{
		"struct":      reflect.ValueOf(rc.structXlsDefinitionFunc),
		"object":      reflect.ValueOf(rc.objectXlsDefinitionFunc),
		"task":        reflect.ValueOf(rc.taskXlsDefinitionFunc),
		"sync":        reflect.ValueOf(rc.syncXlsDefinitionFunc),
		"count":       reflect.ValueOf(rc.countXlsDefinitionFunc),
		"rows":        reflect.ValueOf(rc.rowsXlsDefinitionFunc),
		"samp":        reflect.ValueOf(rc.sampXlsDefinitionFunc),
		"load":        reflect.ValueOf(rc.loadXlsDefinitionFunc),
		"load-output": reflect.ValueOf(rc.loadXlsDefinitionFunc),
		"load-input":  reflect.ValueOf(rc.loadXlsDefinitionFunc),
		"hotSql":      reflect.ValueOf(rc.hotSqlXlsDefinitionFunc),
	}
}
func modeFuncGet(mode string) (map[string]any, map[string]string, map[string]reflect.Type) {
	var (
		sheetTail      map[string]string
		sheetName      map[string]any
		sheetStructMap map[string]reflect.Type
	)
	if l := global.ModeReturnFunc(mode, modeFuncMap()); !l.IsValid() && l.Kind() == reflect.Invalid {
		return nil, nil, nil
	} else {
		m := l.Call(nil)
		for i := 0; i < len(m); i++ {
			if i == 0 {
				sheetName = m[i].Interface().(map[string]any)
			} else if i == 1 {
				sheetTail = m[i].Interface().(map[string]string)
			} else if i == 2 {
				sheetStructMap = m[i].Interface().(map[string]reflect.Type)
			}
		}
	}
	return sheetName, sheetTail, sheetStructMap
}

type xlsLevel struct {
	FileName     string `json:"fileName"`
	SafetySwitch bool   `json:"safetySwitch"`
}
type resultLevel struct {
	Tty           string   `json:"tty"`
	GeneralResult bool     `json:"generalResult"`
	Xls           xlsLevel `json:"xls"`
}

func resultOutSecondaryLevelParameter(mode string, result hocon.Object) (r Result, err error) {
	var (
		resultMap map[string]any
		sheetName map[string]any
		s2        = make(map[string]any)
	)
	if strings.EqualFold(result.String(), "{}") {
		r.GeneralResult = false
		r.Teletypewriter = "bar"
		return
	}
	if resultMap, err = global.StructSubToMapAny(getResult()); err != nil {
		return
	}
	for k, v := range resultMap {
		if r1 := rc.getHoconConfigVal1(result.ToConfig(), k, reflect.TypeOf(v).String()); r1 != nil {
			if reflect.TypeOf(r1).Kind() == reflect.Map {
				for x, y := range r1.(map[string]any) {
					if reflect.TypeOf(y).Kind() == reflect.String {
						r1.(map[string]any)[x] = strings.ReplaceAll(fmt.Sprintf("%v", y), "\"", "")
					}
				}
			}
			s2[k] = r1
		} else {
			s2[k] = v
		}
	}
	if err = global.MapSubToStructSubJsonName(s2, &r); err != nil {
		return
	}
	sheetName, r.XlsV.XlsTailGather, r.XlsV.XlsSheetStructMap = modeFuncGet(mode)
	if v, ok := sheetName["sheetName"]; ok {
		r.XlsV.XlsSheetNameGather = v.([]string)
	}
	if v, ok := sheetName["fileName"]; ok && len(rc.SecondaryL.ResultV.XlsV.XlsFileName) == 0 {
		r.XlsV.XlsFileName = v.(string)
	}
	if v, ok := sheetName["terminal"]; ok && len(rc.SecondaryL.ResultV.XlsV.TerminalSheetName) == 0 {
		r.XlsV.TerminalSheetName = v.(string)
	}
	return
}
